Skip to content

feat(anolisa): add update check#1413

Merged
ikunkun-sys merged 2 commits into
alibaba:mainfrom
kongche-jbw:feature/anolisa/update-check
Jul 9, 2026
Merged

feat(anolisa): add update check#1413
ikunkun-sys merged 2 commits into
alibaba:mainfrom
kongche-jbw:feature/anolisa/update-check

Conversation

@kongche-jbw

Copy link
Copy Markdown
Collaborator

Description

Adds a read-only upgrade-detection entry anolisa update --check for the
RPM / system-image scenario (issue #1410). It reports whether the RPM-owned
CLI and installed RPM components have newer repo candidates, and — with
--target <profile> — which profile default components are missing. It never
applies changes: only read-only rpm -q / dnf repoquery queries, no
PackageTransaction, no installed.toml writes, no repo/adapter persistence
(repo config is loaded via the dry-run path so a missing config is never
written). --motd renders a short, cache-backed summary for a login hook;
--refresh bypasses the cache. Existing update / update self / update all
/ update <component> semantics are unchanged.

Candidate ordering uses a new platform-layer rpm_evr_cmp (a faithful
rpmvercmp port) instead of semver, so real EVRs (epochs, .al4 releases,
two-segment versions) are compared the way dnf would. Applying upgrades is a
separate command (anolisa upgrade, issue #1411).

Related Issue

closes #1410

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional change)
  • Performance improvement
  • CI/CD or build changes

Scope

  • cosh (copilot-shell)
  • cosh-ng (cosh-ng)
  • sec-core (agent-sec-core)
  • skill (os-skills)
  • sight (agentsight)
  • tokenless (tokenless)
  • ckpt (ws-ckpt)
  • memory (agent-memory)
  • anolisa (anolisa-cli)
  • skillfs (SkillFS)
  • Multiple / Project-wide

Checklist

  • I have read the Contributing Guide
  • My code follows the project's code style
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated the documentation accordingly
  • For cosh: Lint passes, type check passes, and tests pass
  • For cosh-ng: cargo clippy --all-targets -- -D warnings and cargo fmt --check pass
  • For sec-core (Rust): cargo clippy -- -D warnings and cargo fmt --check pass
  • For sec-core (Python): Ruff format and pytest pass
  • For skill: Skill directory structure is valid and shell scripts pass syntax check
  • For sight: cargo clippy -- -D warnings and cargo fmt --check pass
  • For tokenless: cargo clippy -- -D warnings and cargo fmt --check pass
  • For memory (Linux only): cargo clippy --all-targets -- -D warnings, cargo fmt --check, and cargo test pass
  • For anolisa: cargo clippy --all-targets --locked -- -D warnings, cargo fmt --all --check, and cargo test --locked pass
  • For skillfs: cargo fmt --all --check, cargo clippy --workspace --all-targets -- -D warnings, and cargo test --workspace pass
  • Lock files are up to date (package-lock.json / Cargo.lock)

Testing

  • cargo test -p anolisa-cli --locked (438 passed) and
    cargo test -p anolisa-platform --locked (77 passed).
  • New update_check_* tests cover: flag parsing/rejection, JSON shape,
    rpm component update/noop, non-semver EVR upgrade detection, raw component
    unsupported_in_rpm_upgrade, missing target-profile defaults, item-level
    query/rpmdb errors, MOTD text/silence, cache round-trip + target-keying,
    and read-only repo-config load.
  • New rpmvercmp / rpm_evr_cmp tests against RPM reference cases (epoch,
    leading zeros, ~/^, numeric-vs-alpha).
  • cargo fmt --all --check, cargo clippy --workspace --all-targets --locked -- -D warnings, and cargo doc --no-deps all clean.

Additional Notes

  • update --check is registered as ReadOnly in the command policy so the
    MOTD hook can run it unprivileged (it is not gated behind the mutating-update
    root requirement).
  • The target-profile reader is intentionally minimal (default_components
    only) since the repo-side profile schema is not finalized; it tolerates
    unknown keys for forward compatibility.
  • Note: --check still issues dnf repoquery for candidates (a read-only,
    network-touching query), which is why the MOTD path is cache-backed.

- add --check/--motd/--refresh/--target flags to update
- detect rpm cli/component upgrades via read-only rpm/dnf queries
- add rpm_evr_cmp/rpmvercmp for correct RPM EVR ordering
- report missing target-profile defaults as installable
- cache update-check reports by target for MOTD use
- keep --check read-only: no dnf transaction or state writes

Assisted-by: Codex
Signed-off-by: 空澈 <kongche.jbw@alibaba-inc.com>
@ikunkun-sys

Copy link
Copy Markdown
Collaborator

审查后我看到 3 个需要处理的问题:

  1. [P1] src/anolisa/crates/anolisa-cli/src/commands/tier1/update/check/render.rs:63
    MOTD 提示用户运行 sudo anolisa upgrade,但这个 PR 没有新增 upgrade 命令。我在 PR 分支验证过:anolisa upgrade --help 会报 unrecognized subcommand 'upgrade'。除非 [anolisa] feat(anolisa): add RPM image upgrade command #1411 会在同一个发布里先合入,否则登录提示会指向一个不可用命令。建议在本 PR 中改成已存在的命令/说明,或先不要在 MOTD 中提示尚未落地的执行命令。

  2. [P2] src/anolisa/crates/anolisa-cli/src/commands.rs:397 / src/anolisa/crates/anolisa-cli/src/commands/tier1/update/check.rs:190
    [anolisa] feat(anolisa): add RPM-only update check for image upgrades #1410 明确说第一阶段只支持 system/RPM 场景,user mode 应该返回明确的 unsupported 结果。但当前 update --check 被注册成 ReadOnly,全局校验会放行 --install-mode userhandle_update_check 里也没有 user-mode guard。我验证 anolisa --install-mode user update --check --json 会返回正常 RPM 检查报告,而不是 unsupported。

  3. [P2] src/anolisa/crates/anolisa-cli/src/commands/tier1/update/check.rs:260
    [anolisa] feat(anolisa): add RPM-only update check for image upgrades #1410--target 应默认使用 repo 声明的默认 profile,但当前实现省略 --target 时就是 None,只有显式传 --target 才会检查 missing defaults。因此普通 anolisa update --check / --motd 不会报告默认组件缺失,削弱了 MOTD 主场景。

我跑过的验证:

  • cargo test -p anolisa-cli --locked update_check:通过,23 个测试
  • cargo test -p anolisa-platform --locked rpm_:通过,52 个测试
  • anolisa --help / anolisa update --help:通过
  • anolisa upgrade --help:失败,确认第 1 个问题

@kongche-jbw

Copy link
Copy Markdown
Collaborator Author

@ikunkun-sys fresh

@ikunkun-sys

Copy link
Copy Markdown
Collaborator

复审了最新 head b0bb2585,旧的三个问题里:

  • MOTD 引用不存在的 anolisa upgrade 已修复。
  • user-mode update --check 现在会明确拒绝,MOTD user-mode 静默返回也已覆盖。
  • 默认 target profile 的方向有更新,但我这里还看到两个新的阻塞点。

Findings

  1. [P1] agentic_os-v1.0.toml 加到了源码树,但安装后不会被分发。load_target_profile_by_name() 对非默认 profile 只查 <etc>/profiles/<name>.toml<datadir>/profiles/<name>.toml,只有 agentic_os-latest 有内置 fallback;而 install-anolisa.sh 目前只 stage manifests/templates/index,RPM spec 也明确不打包 datadir。结果是安装后的用户运行 anolisa update --check --target agentic_os-v1.0 会直接报找不到 profile,除非管理员手工把 toml 放进 /etc 或 datadir。建议把 profiles/ 纳入 install script / bundle / RPM,或者把需要支持的 versioned profile 也编译进 binary。

  2. [P2] 省略 --target 和显式 --target agentic_os-latest 对同一个 target name 会解析出不同 profile 内容。注释说 <etc>/profiles / <datadir>/profiles 应该优先于内置 profile,但 load_effective_target_profile(None) 直接走 load_builtin_default_profile(),绕过了磁盘查找;显式 --target agentic_os-latest 才会走磁盘查找。由于 MOTD cache 也只按 target 名匹配,这会让同名 agentic_os-latest 的报告和缓存语义不一致。建议 omitted target 也调用 load_target_profile_by_name(layout, DEFAULT_TARGET_PROFILE_NAME)

验证

  • cargo test --locked -p anolisa-cli update_check -- --test-threads=1:39 passed
  • cargo test --locked -p anolisa-platform rpm -- --test-threads=1:52 passed
  • cargo build --locked -p anolisa-cli:passed
  • CLI smoke:临时 system prefix 下无 profiles/ 时,--target agentic_os-v1.0 复现 cannot find target profile;手动把 toml 放到 datadir 后同一命令正常输出报告。

@ikunkun-sys

Copy link
Copy Markdown
Collaborator

Follow-up:这里是否需要把 profile TOML 编译进二进制?

现在只有 agentic_os-latest 通过 include_str! 内置进 binary,agentic_os-v1.0 仍依赖安装时落盘。可以明确一下期望模型:

  • 如果 profile 是 CLI release 的一部分,建议把所有 CLI 支持的 release-owned profiles 都编译进去,磁盘文件只作为覆盖/扩展。
  • 如果 profile 是可运营发布的数据资产,那就需要把 profiles/ 加入 install script、manifest bundle 和 RPM 包内容,并保证版本 profile 随安装/升级同步下发。

两种都能工作,但现在是 mixed model:latest 内置,v1.0 不内置且不分发,所以显式 --target agentic_os-v1.0 在干净安装后不可用。

@kongche-jbw kongche-jbw force-pushed the feature/anolisa/update-check branch from 3097f17 to 066a7c6 Compare July 9, 2026 09:15
Use a release-owned latest profile as the default target for
`update --check`, while keeping profile lookup data-driven.

Resolve omitted targets through the same lookup path as explicit
targets so on-disk latest profiles override the built-in fallback.
Keep only the latest bootstrap profile in the binary; versioned target
profiles remain external data assets for the future profile source.
@kongche-jbw kongche-jbw force-pushed the feature/anolisa/update-check branch from 066a7c6 to 8494672 Compare July 9, 2026 09:17
@kongche-jbw

Copy link
Copy Markdown
Collaborator Author

@ikunkun-sys Thanks, updated.

The transition model is now: only agentic_os-latest is embedded as a bootstrap
fallback; versioned profiles remain external data assets for the future profile
source. I removed agentic_os-v1.0.toml to avoid implying that versioned targets
are supported in clean installs before the profile distribution path exists.

Also fixed the lookup inconsistency: omitted --target now goes through the same
load_target_profile_by_name() path as explicit --target agentic_os-latest,
so disk profiles override the built-in fallback consistently.

Verified:

  • cargo fmt --all -- --check
  • cargo test -p anolisa-cli --locked update_check

@ikunkun-sys ikunkun-sys merged commit 99a4111 into alibaba:main Jul 9, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[anolisa] feat(anolisa): add RPM-only update check for image upgrades

2 participants